home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / Key / KeyTables.c < prev   
C/C++ Source or Header  |  1996-09-26  |  27KB  |  1,330 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     keytables.c
  5.  
  6.     DESCRIPTION
  7.     Management for Key-Hashing tables
  8.  
  9.     NOTES
  10.     original from M.Dillon
  11.  
  12.     for the first(!) call of any function of that module,
  13.     the corresponding HASH-table must be clean (setmem(...,0))
  14.  
  15.     BUGS
  16.     thousands - but where
  17.     there may be some inconsistencies
  18.  
  19.     TODO
  20.     new method for management of hashes
  21.  
  22.     EXAMPLES
  23.  
  24.     SEE ALSO
  25.     keycodes.c keycom.c keycontrol.c
  26.  
  27.     INDEX
  28.  
  29.     HISTORY
  30.     14-Dec-92  b_null created
  31.     15-Dez-92  b_null modified
  32.     15-Dez-92  b_null docs updated, some checks added
  33.     16-Dez-92  b_null documented
  34.     16 Jun 93  b_null introduced "struct keyspec"
  35.     29-Jun-94  b_null Docs updated
  36.     $Date: 94/07/06 12:06:48 $ last update
  37.  
  38. ******************************************************************************/
  39.  
  40. /**************************************
  41.         Includes
  42. **************************************/
  43. #define  KEY_INTERNAL
  44. #include "defs.h"
  45. #include <devices/keymap.h>
  46. #include <devices/console.h>
  47. #include "keyhashes.h"
  48. #ifdef PATCH_NULL
  49. #include "AUTO.h"
  50. #else
  51. #define MK_AUTOEXIT(x) void x (void)
  52. #define MK_AUTOINIT(x) void x (void)
  53. #endif /*  */
  54.  
  55.  
  56. /**************************************
  57.         Globale Variable
  58. **************************************/
  59.  
  60. Prototype void     keyload    (KEYTABLE * kt, char * name);
  61. Prototype void     keysave    (KEYTABLE * kt, char * name);
  62. Prototype int     loadkeys    (KEYTABLE * kt, FILE * fi, int * lineno);
  63. Prototype int     savekeys    (KEYTABLE * kt, FILE * fo);
  64. Prototype HASH * findhash    (KEYTABLE * kt, KEYSPEC *ks,       UBYTE *);
  65. Prototype APTR     keyspec2macro    (KEYTABLE * kt,              const UBYTE *);
  66. Prototype int     resethash    (KEYTABLE * kt);
  67. Prototype int     unmapkey    (KEYTABLE * kt, const UBYTE *key);
  68. Prototype int     mapkey     (KEYTABLE * kt, const UBYTE *key, const UBYTE *value, const UBYTE *help);
  69. Prototype int     remhash    (KEYTABLE * kt, KEYSPEC *ks);
  70. Prototype int     addhash    (KEYTABLE * kt, KEYSPEC *ks, const UBYTE *comm, const UBYTE *help);
  71. Prototype void     dealloc_hash    (KEYTABLE * kt);
  72.  
  73. Prototype KEYTABLE * get_keytable    (char * name);
  74. Prototype KEYTABLE * new_keytable    (char * name, int defaults);
  75. Prototype void         delete_keytable (KEYTABLE * kt, int force);
  76.  
  77. Prototype void         exit_keytables (void);
  78.  
  79. /**************************************
  80.       Interne Defines & Strukturen
  81. **************************************/
  82.  
  83. #ifndef QUAL_UP
  84. #define QUAL_UP 0x80
  85. #endif
  86.  
  87.  
  88. /**************************************
  89.         Interne Variable
  90. **************************************/
  91. /* extern TWOSTRINGS defmap[]; */
  92. #include "defmap.h"
  93.  
  94.  
  95. /* this is the list of all keytables */
  96. static struct MinList KeyTables = { (struct MinNode *)&KeyTables.mlh_Tail,
  97.     NULL, (struct MinNode *)&KeyTables.mlh_Head };
  98.  
  99. /**************************************
  100.        Interne Prototypes
  101. **************************************/
  102.  
  103.  
  104.  
  105. /*****************************************************************************
  106.  
  107.     NAME
  108.     freehash
  109.  
  110.     PARAMETER
  111.     HASH * hash
  112.  
  113.     RESULT
  114.     the hash->next entry if existing
  115.     NULL if hash == NULL
  116.  
  117.     RETURN
  118.     HASH *
  119.  
  120.     DESCRIPTION
  121.     free a hash-entry and all associated data
  122.  
  123.     NOTES
  124.     the free'd hash must not be entry in a hashtable,
  125.     as we do not take care of any refernces, but only
  126.     of hash, comm and help
  127.  
  128.     BUGS
  129.  
  130.     EXAMPLES
  131.  
  132.     SEE ALSO
  133.  
  134.     INTERNALS
  135.  
  136.     HISTORY
  137.     23 Jan 1993 b_null created
  138.  
  139. ******************************************************************************/
  140.  
  141. HASH * freehash (HASH * hash)
  142. {
  143.     HASH * next = NULL;
  144.  
  145.     if (hash) {
  146.     next = hash->next;
  147.     if (hash->comm) {
  148.         DeallocFunc (hash->comm);
  149.     } /* if */
  150.     if (hash->help) {
  151.         DeallocFunc (hash->help);
  152.     } /* if */
  153.     FreeFunc(hash, sizeof(HASH));
  154.     } /* if */
  155.  
  156.     return (next);
  157. } /* freehash */
  158.  
  159.  
  160.  
  161. /*****************************************************************************
  162.  
  163.     NAME
  164.     addhash
  165.  
  166.     PARAMETER
  167.     KEYTABLE    * kt
  168.     KEYSPEC     * ks
  169.     const UBYTE * comm
  170.     const UBYTE * help
  171.  
  172.     RESULT
  173.     success: RET_SUCC == ok; RET_FAIL == failure
  174.  
  175.     RETURN
  176.     int
  177.  
  178.     DESCRIPTION
  179.     create a new hash-entry for a known hash
  180.     if there is already an existing one with the same code/qual
  181.     simply change its command
  182.  
  183.     NOTES
  184.     that function is called by mapkey
  185.  
  186.     BUGS
  187.     WARNING : WE DO NOT LOOK FOR A SETTING OF help YET !!!
  188.  
  189.     EXAMPLES
  190.  
  191.     SEE ALSO
  192.  
  193.     INTERNALS
  194.     finde den hash-slot
  195.     falls der eintrag schon existiert, ersetze den comm
  196.     sonst erstelle einen neuen eintrag
  197.     falls nicht alles funktionierte, stelle den alten zustand wieder her
  198.  
  199.     HISTORY
  200.     14-Dec-92  b_null included & modified
  201.     16-Dec-92  b_null added handling of "nolink"
  202.  
  203. ******************************************************************************/
  204.  
  205. int addhash (KEYTABLE * kt, KEYSPEC * ks, const UBYTE * comm, const UBYTE * help)
  206. {
  207.     HASH ** p,
  208.       * hash;
  209. //    APTR    oldcomm = NULL;
  210.  
  211.     if (kt == NULL) {
  212.     return (RET_FAIL);
  213.     } /* if empty or missing table */
  214.  
  215.     hash = *(p = &KT_SLOT(kt,ks));
  216.  
  217.     while (hash) {
  218.     if (KS_MATCH_EXACT(&hash->key, ks)) {
  219.         goto newstr;
  220.     } /* if found old */
  221.     hash = *(p = &hash->next);
  222.     } /* while entries left */
  223.  
  224.     if (!(hash  = (HASH *)AllocFunc (sizeof (HASH), MEMF_ANY|MEMF_CLEAR))) {
  225.     globalflags.Abortcommand = 1;
  226.     return (RET_FAIL);
  227.     } /* if nomemory */
  228. /*    clrmem (hash, sizeof (HASH)); */
  229.  
  230.     hash->next = NULL;
  231.     KS_COPY(&hash->key,ks);
  232.  
  233. newstr:
  234.     /* oldcomm = hash->comm; */
  235.     DeallocFunc (hash->comm);
  236.     DeallocFunc (hash->help);
  237.  
  238.     hash->comm = DupFunc (comm, 0);
  239.     hash->help = DupFunc (help, 0);
  240.  
  241.     if ((!hash->comm) /* || (!hash->help) */ /* || (oldcomm == hash->comm) */) {
  242.     *p = freehash (hash);
  243.     return (RET_FAIL);
  244.     } /* if something went wrong */
  245.  
  246.     /* everything worked fine - insert it into the table */
  247.     *p = hash;
  248.     return (RET_SUCC);
  249. } /* addhash */
  250.  
  251.  
  252.  
  253. /*****************************************************************************
  254.  
  255.     NAME
  256.     remhash
  257.  
  258.     PARAMETER
  259.     KEYTABLE * kt
  260.     KEYSPEC  * ks
  261.  
  262.     RESULT
  263.     success:
  264.         RET_SUCC == ok;
  265.         RET_FAIL == failure or not found
  266.  
  267.     RETURN
  268.     int
  269.  
  270.     DESCRIPTION
  271.     delete an existing hashentry
  272.  
  273.     NOTES
  274.     that function is called by unmapkey
  275.  
  276.     BUGS
  277.  
  278.     EXAMPLES
  279.  
  280.     SEE ALSO
  281.  
  282.     INTERNALS
  283.     finde den hash-slot
  284.     falls der eintrag existiert, loesche ihn und seinen link
  285.     sonst mache gar nichts
  286.  
  287.     HISTORY
  288.     14-Dec-92  b_null included & modified
  289.     23-Jan-93  b_null used freehash
  290.  
  291. ******************************************************************************/
  292.  
  293. int remhash (KEYTABLE * kt, KEYSPEC * ks)
  294. {
  295.     HASH *  hash, /* current */
  296.      ** p;      /* previous */
  297.  
  298.     if (kt == NULL) {
  299.     return (RET_FAIL);
  300.     } /* if empty or missing table */
  301.  
  302.     hash = *(p = &KT_SLOT(kt,ks));
  303.     while (hash) {
  304.     if (KS_MATCH_EXACT(&hash->key, ks)) {
  305.         *p = freehash (hash);
  306.         return   (RET_SUCC);
  307.     } /* if found */
  308.     hash = *(p = &hash->next);
  309.     } /* while searching */
  310.  
  311.     /* not found: */
  312.     return (RET_FAIL);
  313. } /* remhash */
  314.  
  315.  
  316.  
  317. /*****************************************************************************
  318.  
  319.     NAME
  320.     mapkey
  321.  
  322.     PARAMETER
  323.     KEYTABLE    * kt
  324.     const UBYTE * key
  325.     const UBYTE * value
  326.     const UBYTE * help
  327.  
  328.     RESULT
  329.     success:
  330.         RET_FAIL == error
  331.         RET_OK   == everything ok
  332.  
  333.     RETURN
  334.     int
  335.  
  336.     DESCRIPTION
  337.     first abstraction for addhash
  338.     which uses an ascii-name
  339.  
  340.     NOTES
  341.     this function might call error()
  342.  
  343.     BUGS
  344.  
  345.     EXAMPLES
  346.  
  347.     SEE ALSO
  348.     addhash, unmapkey
  349.  
  350.     INTERNALS
  351.     falls es sich um einen gueltigen map handelt
  352.         belege ihn (neu)
  353.     sonst gebe eine fehlermeldung aus
  354.  
  355.     HISTORY
  356.     14-Dec-92  b_null included & modified
  357.     23-Jan-93  b_null void -> int
  358.  
  359. ******************************************************************************/
  360.  
  361. int mapkey (KEYTABLE * kt, const UBYTE * key, const UBYTE * value, const UBYTE *help)
  362. {
  363.     struct keyspec ks;
  364.  
  365.     if (get_codequal (key, &ks)) {
  366.     return (addhash (kt, &ks, value, help));
  367.     } else {
  368.     error ("%s:\nUnknown Key '%s'", CommandName(), key);
  369.     }
  370.     return (RET_FAIL);
  371. } /* mapkey */
  372.  
  373.  
  374.  
  375. /*****************************************************************************
  376.  
  377.     NAME
  378.     unmapkey
  379.  
  380.     PARAMETER
  381.     KEYTABLE    * kt
  382.     const UBYTE * key
  383.  
  384.     RESULT
  385.     success:
  386.         RET_FAIL == error
  387.         RET_OK   == everything ok
  388.  
  389.     RETURN
  390.     int
  391.  
  392.     DESCRIPTION
  393.     first abstraction for remhash
  394.     which uses an ascii-name
  395.  
  396.     NOTES
  397.     this function might call error()
  398.  
  399.     BUGS
  400.  
  401.     EXAMPLES
  402.  
  403.     SEE ALSO
  404.     remhash, mapkey
  405.  
  406.     INTERNALS
  407.     falls es sich um einen gueltigen map handelt
  408.         loesche seine belegung
  409.     sonst gebe eine fehlermeldung aus
  410.  
  411.     HISTORY
  412.     14-Dec-92  b_null included & modified
  413.     23-Jan-93  b_null void -> int
  414.  
  415. ******************************************************************************/
  416.  
  417. int unmapkey (KEYTABLE * kt, const UBYTE * key)
  418. {
  419.     struct keyspec ks;
  420.  
  421.     if (get_codequal (key, &ks)) {
  422.     return (remhash (kt, &ks));
  423.     } else {
  424.     error ("%s:\nUnknown Key '%s'", CommandName(), key);
  425.     }
  426.     return (RET_FAIL);
  427. } /* unmapkey */
  428.  
  429.  
  430.  
  431. /*****************************************************************************
  432.  
  433.     NAME
  434.     dealloc_hash
  435.  
  436.     PARAMETER
  437.     KEYTABLE * kt
  438.  
  439.     RESULT
  440.     -/-
  441.  
  442.     RETURN
  443.     void
  444.  
  445.     DESCRIPTION
  446.     frees all Hash-entries in a key-table
  447.  
  448.     NOTES
  449.  
  450.     BUGS
  451.  
  452.     EXAMPLES
  453.  
  454.     SEE ALSO
  455.  
  456.     INTERNALS
  457.     ueber allen hash-slots
  458.         loesche jeden eintrag des hash-slots
  459.  
  460.     HISTORY
  461.     14-Dec-92  b_null included & modified
  462.  
  463. ******************************************************************************/
  464.  
  465. void dealloc_hash ( KEYTABLE * kt )
  466. {
  467.     HASH * hash,
  468.      * hnext = NULL;  /* save ptr to the next entry when freeing the current */
  469.     WORD   i;
  470.  
  471.     if (kt == NULL) {
  472.     return;
  473.     } /* if empty or missing table */
  474.  
  475.     for (i = 0; i < HASHSIZE; i++) {
  476.     for (hash = kt->hash[i]; hash; hash = hnext) {
  477.         hnext = freehash (hash);
  478.     } /* for */
  479.     kt->hash[i] = NULL;
  480.     } /* for */
  481. } /* dealloc_hash */
  482.  
  483.  
  484.  
  485. /*****************************************************************************
  486.  
  487.     NAME
  488.     resethash
  489.  
  490.     PARAMETER
  491.     KEYTABLE * kt
  492.  
  493.     RESULT
  494.     success:
  495.         RET_FAIL == error (might have worked partially)
  496.         RET_OK   == everything ok
  497.  
  498.     RETURN
  499.     int
  500.  
  501.     DESCRIPTION
  502.     dealloc all entries of a hashtable and then
  503.     set its contents to default-values
  504.  
  505.     NOTES
  506.     the defaults are stored in an array
  507.     called defmap
  508.  
  509.     BUGS
  510.  
  511.     EXAMPLES
  512.  
  513.     SEE ALSO
  514.     mapkey, dealloc_hash
  515.  
  516.     INTERNALS
  517.     loesche die tabelle
  518.     solange noch ein gueltiger eintrag in defmap ist (und alles gutging)
  519.         erzeuge eine map fuer ihn
  520.  
  521.     HISTORY
  522.     14-Dec-92  b_null included
  523.     16-Dec-92  b_null documented
  524.  
  525. ******************************************************************************/
  526.  
  527. int resethash (KEYTABLE * kt)
  528. {
  529.     WORD i;
  530.  
  531.     if (kt == NULL) {
  532.     return (RET_FAIL);
  533.     } /* if empty or missing table */
  534.  
  535.     dealloc_hash (kt);
  536.  
  537.     for (i = 0; defmap[i].from; ++i) {
  538.     if (!mapkey (kt, defmap[i].from, defmap[i].to, NULL)) { /* ,defmap[i].help)) */
  539.         return (RET_FAIL);
  540.     } /* if error */
  541.     } /* for defmap-entries */
  542.  
  543.     return (RET_SUCC);
  544. } /* resethash */
  545.  
  546.  
  547.  
  548. /*****************************************************************************
  549.  
  550.     NAME
  551.     findhash
  552.  
  553.     PARAMETER
  554.     KEYTABLE *kt
  555.     KEYSPEC  *ks
  556.     UBYTE     *hint ; oder ULONG pkeys
  557.                ; additional info to be used if the key is unmapped
  558.  
  559.     RESULT
  560.     the hash-entry associated with code and qual
  561.  
  562.     RETURN
  563.     HASH *
  564.  
  565.     DESCRIPTION
  566.     simple searching
  567.  
  568.     NOTES
  569.     this routine is part of keyspec2macro
  570.  
  571.     BUGS
  572.  
  573.     EXAMPLES
  574.  
  575.     SEE ALSO
  576.     keyspec2macro
  577.  
  578.     INTERNALS
  579.     finde den richtigen slot
  580.     solange es noch eintraege in dem slot gibe, und der richtige nicht
  581.         gefunden ist,
  582.         gehe zum naechsten eintrag
  583.     wenn du was gefunden hast, gib es aus, sonst NULL
  584.  
  585.     HISTORY
  586.     16-Dec-92  b_null created
  587.  
  588. ******************************************************************************/
  589.  
  590. HASH * findhash (KEYTABLE *kt, KEYSPEC *ks, UBYTE *hint)
  591. {
  592.     HASH * hash;
  593.  
  594.     if (kt == NULL) {
  595.     return (NULL);
  596.     } /* if empty or missing table */
  597.  
  598.     /* PATCH_NULL [11 Mar 1994] : added for better recognition */
  599.     for (hash = KT_SLOT(kt,ks); hash; hash = hash->next) {
  600.     if (KS_MATCH_EXACT(&hash->key,ks)) {
  601.         return (hash);
  602.     } /* if */
  603.     } /* for */
  604.  
  605.     for (hash = KT_SLOT(kt,ks); hash; hash = hash->next) {
  606.     if (KS_MATCH_APPROX(&hash->key,ks)) {
  607.         return (hash);
  608.     } /* if */
  609.     } /* for */
  610.  
  611.     /* PATCH_NULL [02 Apr 1993] : we can not call that proc on unmapped keys yet >>> */
  612. #ifndef NOT_DEF
  613.     {
  614.     static HASH retdummy;      /* static, 'coz we return a ptr to that data */
  615.     static char rdchars[36];
  616.  
  617.     /* we have to create a dummy-Intuimessage and call RawKeyConvert with it */
  618.     struct InputEvent ie = { NULL, IECLASS_RAWKEY, 0, 0, 0, NULL, 0L,0L};
  619.     long        len;
  620.  
  621.     if (hint) {                       /* PATCH_NULL 27-06-94      */
  622.         strcpy (rdchars, hint);/* That dirty Hack is added */
  623.         goto findhash_dummyfound;        /* to reenable DeadKeys    */
  624.     } /* if */
  625.  
  626.     ie.ie_Code           = KS_CODE(ks);
  627.     ie.ie_Qualifier        = qual2iqual(KS_QUAL(ks));
  628.     /* ie.ie_position.ie_addr = (APTR)pkeys; */
  629.  
  630.     if (IsRawC(ks) && (len = RawKeyConvert (&ie, rdchars+1, 36-2, NULL) > 0)) { /* PATCH_NULL 27-06-94 changed ">" into ">=" to reenable Deadkeys */
  631. /* printf("PseudoMap:   l=%ld; c=%s\n", len, rdchars+1); */
  632.         rdchars[0] = '\'';
  633.         rdchars[len+1] = '\0';
  634.         /* previously : */
  635.         /* if (len == 1) {           */
  636.         /*      rdchars[0] = '\'';     */
  637.         /*      rdchars[len+1] = '\0'; */
  638.         /* } else {          */
  639.         /*      rdchars[0]     = '`';  */
  640.         /*      rdchars[len+1] = '\''; */
  641.         /* }             */
  642.  
  643. findhash_dummyfound:
  644.         KS_COPY(&retdummy.key,ks);
  645.         retdummy.comm = rdchars;
  646.         retdummy.help = "unmapped Key!";
  647.         return (&retdummy);
  648.     } /* if */
  649. /* printf("NOPseudoMap: r?=%s;\n", IsRawC(ks)?"Y":"N"); */
  650.  
  651.     }
  652. #endif /* NOT_DEF */
  653.     /* PATCH_NULL [02 Apr 1993] : we can not call that proc on unmapped keys yet <<< */
  654.  
  655.     return (NULL);
  656. } /* findhash */
  657.  
  658.  
  659.  
  660. /*****************************************************************************
  661.  
  662.     NAME
  663.     keyspectohash
  664.  
  665.     PARAMETER
  666.     KEYTABLE    *kt
  667.     const UBYTE *str
  668.  
  669.     RESULT
  670.     the Hashentry associated with
  671.     the name str
  672.  
  673.     RETURN
  674.     HASH *
  675.  
  676.     DESCRIPTION
  677.     transform str into a Hash-value and search for its entry
  678.  
  679.     NOTES
  680.     this routine uses findhash
  681.  
  682.     BUGS
  683.  
  684.     EXAMPLES
  685.  
  686.     SEE ALSO
  687.     findhash
  688.  
  689.     INTERNALS
  690.     falls es sich um einen gueltigen schluessel handelt,
  691.         finde eine passenden eintrag und
  692.         gib ihn aus
  693.     sonst gib NULL aus
  694.  
  695.     HISTORY
  696.     23-Jan-93  b_null created
  697.  
  698. ******************************************************************************/
  699.  
  700. HASH * keyspectohash (KEYTABLE * kt, const UBYTE *str)
  701. {
  702.     struct keyspec ks;
  703.  
  704.     if (get_codequal (str, &ks)) {
  705.     return (findhash (kt, &ks, 0));
  706.     } /* if is key */
  707.     return (NULL);
  708. } /* keyspectohash */
  709.  
  710.  
  711.  
  712. /*****************************************************************************
  713.  
  714.     NAME
  715.     keyspec2macro
  716.  
  717.     PARAMETER
  718.     KEYTABLE    * kt
  719.     const UBYTE * str
  720.  
  721.     RESULT
  722.     the macro-field of the Hashentry associated with
  723.     the name str
  724.  
  725.     RETURN
  726.     APTR
  727.  
  728.     DESCRIPTION
  729.     transform str into a Hash-value and search for its entry
  730.     then return its command-entry
  731.  
  732.     NOTES
  733.     this routine is splitted into
  734.     two minor ones by putting the searching
  735.     into another routine called findhash&keyspectohash
  736.  
  737.     BUGS
  738.  
  739.     EXAMPLES
  740.  
  741.     SEE ALSO
  742.     findhash
  743.  
  744.     INTERNALS
  745.     finde den passenden eintrag
  746.         und gib dessen comm aus
  747.  
  748.     HISTORY
  749.     14-Dec-92  b_null included
  750.     16-Dec-92  b_null splitted & documented
  751.  
  752. ******************************************************************************/
  753.  
  754. APTR keyspec2macro (KEYTABLE * kt, const UBYTE * str)
  755. {
  756.     HASH *hash;
  757.  
  758.     hash = keyspectohash (kt, str);
  759.     if (hash) {
  760.     return (hash->comm);
  761.     } /* if */
  762.     return (NULL);
  763. } /* keyspec2macro */
  764.  
  765.  
  766. /*****************************************************************************
  767.  
  768.     NAME
  769.     savekeys
  770.  
  771.     PARAMETER
  772.     KEYTABLE * kt
  773.     FILE *    fi
  774.  
  775.     RESULT
  776.     success:
  777.         RET_FAIL == error
  778.         RET_OK   == everything ok
  779.  
  780.     RETURN
  781.     int
  782.  
  783.     DESCRIPTION
  784.     write a special keymap file
  785.     or the keymap section of a file
  786.     such a section can be read with loadkeys
  787.  
  788.     NOTES
  789.     currently the keymap-section is in ascii
  790.     format - this may be changed to IFF
  791.     this function is separated from keysave for use in packages
  792.  
  793.     BUGS
  794.  
  795.     EXAMPLES
  796.  
  797.     SEE ALSO
  798.     loadkeys
  799.  
  800.     INTERNALS
  801.     schreibe einen header
  802.     gehe alle slots entlang und
  803.         schreibe alle eintraege der slots
  804.     schreibe einen footer
  805.  
  806.     HISTORY
  807.     14-Dec-92  b_null included
  808.     16-Dec-92  b_null documented
  809.  
  810. ******************************************************************************/
  811.  
  812. int savekeys (KEYTABLE * kt, FILE * fo)
  813. {
  814.     HASH * hash;
  815.     int    i;
  816.  
  817.     if (kt == NULL) {
  818.     return (RET_FAIL);
  819.     } /* if empty or missing table */
  820.  
  821.     fprintf(fo, "KEYLIST START\n");
  822.     for (i = 0; i < HASHSIZE; i++) {
  823.     for (hash = kt->hash[i]; hash; hash = hash->next) {
  824.         fprintf (fo, "\tKEY   %s\n", cqtoa (&hash->key));
  825. /* --- THAT BLOCK MUST BE CHANGED IF MACROS ARE MODIFIED */
  826.         if (hash->help)
  827.         fprintf (fo, "\t HELP %s\n", hash->help);
  828.         fprintf (fo, "\t COM  %s\n", hash->comm);
  829. /* --- THAT BLOCK MUST BE CHANGED IF MACROS ARE MODIFIED */
  830.     } /* for keys */
  831.     } /* for hashes */
  832.     fprintf(fo, "KEYLIST END\n");
  833.     return (RET_SUCC);
  834. } /* savekeys */
  835.  
  836.  
  837.  
  838. /*****************************************************************************
  839.  
  840.     NAME
  841.     loadkeys
  842.  
  843.     PARAMETER
  844.     KEYTABLE * kt
  845.     FILE *    fi
  846.     int  *    lineno
  847.  
  848.     RESULT
  849.     success:
  850.         RET_FAIL == error
  851.         RET_OK   == everything ok
  852.  
  853.     RETURN
  854.     int
  855.  
  856.     DESCRIPTION
  857.     read a special Keymap-File
  858.     or the Keymap-section of a file
  859.     which was created with savekeys
  860.  
  861.     NOTES
  862.     this function might call error()
  863.     this function is separated from keyload for use in packages
  864.     can not support "help" yet
  865.  
  866.     BUGS
  867.  
  868.     EXAMPLES
  869.  
  870.     SEE ALSO
  871.     savekeys
  872.  
  873.     INTERNALS
  874.     lese den header
  875.     solange alles gutging und der footer nicht erreicht wurde
  876.         lese nacheinander schluessel
  877.         und macro
  878.         falls eine Zeile nicht in diese Sequenz passt ABBRUCH
  879.  
  880.     das muss geaendert werden:
  881.     lese den header
  882.     solange alles gutging und der footer nicht erreicht wurde
  883.     lese  schluessel und
  884.     danach macro (und evtl help)
  885.         da die reihenfolge von macro und help variieren kann,
  886.            darf der naechste addhash erst durchgefuehrt werden beim naechsten KEY oder bei KEYLIST END
  887.  
  888.     HISTORY
  889.     14-Dec-92  b_null included
  890.     16-Dec-92  b_null documented
  891.  
  892. ******************************************************************************/
  893.  
  894. #define next_nonblank(buf) {while (*buf && *buf<33) buf++; }
  895.  
  896. int loadkeys (KEYTABLE * kt, FILE * fi, int * lineno)
  897. {
  898.     char * buf;
  899.     char   nkey   [128];
  900.     char   help   [128];
  901.     char   body   [LINE_LENGTH];
  902.  
  903.     if (kt == NULL) {
  904.     return (RET_FAIL);
  905.     } /* if empty or missing table */
  906.  
  907.     buf = getnextcomline (fi, lineno);
  908.  
  909.     if (!buf) {
  910.     globalflags.Abortcommand = 1;
  911.     return (RET_FAIL);
  912.     } /* if */
  913.     if (strncmp(buf, "KEYLIST START", 13) != 0) {
  914.     error  ("No Keystart header");
  915.     return (RET_FAIL);
  916.     } /* if */
  917.  
  918.     nkey  [0] = 0;
  919.     help  [0] = 0;
  920.     body  [0] = 0;
  921.  
  922.     while (globalflags.Abortcommand == 0) {
  923.     buf = getnextcomline(fi, lineno);
  924. /* printf("read %s\n", buf); */
  925.     if (!buf) {
  926.         globalflags.Abortcommand = 1;
  927.         return (RET_FAIL);
  928.     } /* if */
  929.  
  930.     if (strncmp(buf, "KEYLIST END", 11) == 0) {
  931.         return (RET_SUCC);
  932.     } else if (strncmp(buf, "KEY ", 4) == 0) {
  933.         buf += 3;
  934.         next_nonblank(buf);
  935.         if (nkey[0] != 0) {
  936.         error  ("<%s:\nDeclared Key w/out Body '%s'", CommandName(), buf);
  937.         return (RET_FAIL);
  938.         } /* if */
  939.         strncpy(nkey, buf, 128);
  940. #ifndef NOT_DEF
  941.     } else if (strncmp(buf, "HELP", 4) == 0) {
  942.         buf += 4;
  943.         next_nonblank(buf);
  944.         if (nkey[0] == 0) {
  945.         error  ("<%s:\nDeclared Help w/out a Key", CommandName(), buf);
  946.         return (RET_FAIL);
  947.         } /* if */
  948.         strncpy(help, buf, 128);
  949. #endif
  950.     } else if (strncmp (buf, "COM", 3) == 0) {
  951.         buf += 3;
  952.         next_nonblank(buf);
  953.         if (nkey[0] == 0) {
  954.         error  ("<%s:\nDeclared Body w/out a Key", CommandName());
  955.         return (RET_FAIL);
  956.         } /* if */
  957.         strncpy (body, buf, LINE_LENGTH);
  958.         mapkey  (kt, nkey, body, help[0]? help: NULL);
  959.         help[0] = 0;
  960.         nkey[0] = 0;
  961.     } else {
  962.         error  ("%s:\nunknown identifier '%s'", CommandName(), buf);
  963.         return (RET_FAIL);
  964.     } /* if types */
  965.     } /* while not ready */
  966.     return (RET_FAIL);
  967. } /* loadkeys */
  968.  
  969.  
  970. /*****************************************************************************
  971.  
  972.     NAME
  973.     keysave
  974.  
  975.     PARAMETER
  976.     KEYTABLE * kt
  977.     char *    name
  978.  
  979.     RESULT
  980.     -/-
  981.  
  982.     RETURN
  983.     void
  984.  
  985.     DESCRIPTION
  986.     first abstraction of savekeys to single files:
  987.     handling of open&close
  988.  
  989.     NOTES
  990.  
  991.     BUGS
  992.  
  993.     EXAMPLES
  994.  
  995.     SEE ALSO
  996.     savekeys
  997.  
  998.     INTERNALS
  999.     oeffne ein file
  1000.     falls das ging,
  1001.         lese die enthaltenen mappings
  1002.         und schliesse es
  1003.     sonst gib einen Fehler aus
  1004.  
  1005.     HISTORY
  1006.     14-Dec-92  b_null included
  1007.     16-Dec-92  b_null renamed & documented
  1008.  
  1009. ******************************************************************************/
  1010.  
  1011. void keysave (KEYTABLE * kt, char * name)
  1012. {
  1013.     FILE * fo = NULL;
  1014.  
  1015.     if (fo = fopen (name, "w")) {
  1016.     savekeys (kt, fo);
  1017.     fclose (fo);
  1018.     } else {
  1019.     error ("%s:\nCan't open file %s for output", CommandName(), name);
  1020.     } /* if */
  1021. } /* keysave */
  1022.  
  1023.  
  1024. /*****************************************************************************
  1025.  
  1026.     NAME
  1027.     keyload
  1028.  
  1029.     PARAMETER
  1030.     KEYTABLE * kt
  1031.     char *    name
  1032.  
  1033.     RESULT
  1034.     -/-
  1035.  
  1036.     RETURN
  1037.     void
  1038.  
  1039.     DESCRIPTION
  1040.     first abstraction of loadkeys to single files:
  1041.     handling of open & close
  1042.  
  1043.     NOTES
  1044.  
  1045.     BUGS
  1046.  
  1047.     EXAMPLES
  1048.  
  1049.     SEE ALSO
  1050.     loadkeys
  1051.  
  1052.     INTERNALS
  1053.     oeffne ein file
  1054.     falls das ging,
  1055.         schreibe die aktuellen mappings hinein
  1056.         und schliesse es
  1057.     sonst gib einen Fehler aus
  1058.  
  1059.     HISTORY
  1060.     14-Dec-92  b_null included
  1061.     16-Dec-92  b_null renamed & documented
  1062.  
  1063. ******************************************************************************/
  1064.  
  1065. void keyload (KEYTABLE * kt, char * name)
  1066. {
  1067.     FILE * fi      = NULL;
  1068.     int    lineno = 0;
  1069.  
  1070.     if (fi = fopen (name, "r")) {
  1071.     dealloc_hash (kt);
  1072.     loadkeys (kt, fi, &lineno);
  1073.     fclose (fi);
  1074.     } else {
  1075.     error ("%s:\nCan't open file %s for input", CommandName(), name);
  1076.     } /* if */
  1077. } /* keyload */
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083. /*****************************************************************************
  1084.  
  1085.     BASIC FUNCTIONS ON KEYTABLES :
  1086.  
  1087.     get, new, delete
  1088.  
  1089.     all keytables created with new_keytable are deleted at program termination
  1090.  
  1091. *****************************************************************************/
  1092.  
  1093. /*****************************************************************************
  1094.  
  1095.     NAME
  1096.     get_keytable
  1097.  
  1098.     PARAMETER
  1099.     char * name
  1100.  
  1101.     RESULT
  1102.     the keytable with the name name, if it is already existing
  1103.     else NULL
  1104.  
  1105.     RETURN
  1106.     KEYTABLE *
  1107.  
  1108.     DESCRIPTION
  1109.     search function on the hidden list of keytables
  1110.  
  1111.     NOTES
  1112.     useful only, if we are using multiple keytables
  1113.  
  1114.     BUGS
  1115.  
  1116.     EXAMPLES
  1117.  
  1118.     SEE ALSO
  1119.  
  1120.     INTERNALS
  1121.  
  1122.     HISTORY
  1123.     27 Jan 1993 b_null created
  1124.  
  1125. ******************************************************************************/
  1126.  
  1127. KEYTABLE * get_keytable (char * name)
  1128. {
  1129.     KEYTABLE * kt;
  1130.  
  1131.     if (name == NULL) {
  1132.     return (GetHead (&KeyTables));
  1133.     } /* if wanted default */
  1134.  
  1135.     for (kt = GetHead(&KeyTables); kt; kt = GetSucc(kt)) {
  1136.     if (strcmp (kt->node.ln_Name, name) == 0) {
  1137.         return (kt);
  1138.     } /* if */
  1139.     } /* for */
  1140.     return (NULL);
  1141. } /* get_keytable */
  1142.  
  1143.  
  1144.  
  1145. /*****************************************************************************
  1146.  
  1147.     NAME
  1148.     delete_keytable
  1149.  
  1150.     PARAMETER
  1151.     KEYTABLE * kt
  1152.     int       force
  1153.  
  1154.     RESULT
  1155.     -/-
  1156.  
  1157.     RETURN
  1158.     void
  1159.  
  1160.     DESCRIPTION
  1161.     delete a full keytable
  1162.     that function does NOT dlete the last keytable,
  1163.     unless force is set to 1
  1164.  
  1165.     NOTES
  1166.     useful only, if we are using multiple keytables
  1167.  
  1168.     that function does NOT take care of any references to a keytable
  1169.     You must do that job on a higher abstraction-level
  1170.         (e.g. in keycom.c - for all ED's if )
  1171.  
  1172.     BUGS
  1173.  
  1174.     EXAMPLES
  1175.  
  1176.     SEE ALSO
  1177.  
  1178.     INTERNALS
  1179.     ausklinken aus der keytable-liste
  1180.     loeschen der hash-entries
  1181.     loeschen des namens
  1182.     loeschen des bodies
  1183.  
  1184.     HISTORY
  1185.     27 Jan 1993 b_null created
  1186.  
  1187. ******************************************************************************/
  1188.  
  1189. void delete_keytable (KEYTABLE * kt, int force)
  1190. {
  1191.     if (kt) {
  1192.     Remove        (&kt->node);
  1193.     if ((!force) && (!GetHead (&KeyTables))) {
  1194.         AddHead ((struct List *)&KeyTables, &kt->node);
  1195.         return;
  1196.     } /* if */
  1197.  
  1198.     dealloc_hash (kt);
  1199.     DeallocFunc  (kt->node.ln_Name);
  1200.     FreeFunc     (kt, sizeof(KEYTABLE));
  1201.     } /* if */
  1202. } /* delete_keytable */
  1203.  
  1204.  
  1205.  
  1206. /*****************************************************************************
  1207.  
  1208.     NAME
  1209.     new_keytable
  1210.  
  1211.     PARAMETER
  1212.     char * name
  1213.     int    defaults
  1214.  
  1215.     RESULT
  1216.     either a new keytable, if there is not already one with that name
  1217.     or the first keytable, that matches that name
  1218.     if we have to create a new one, we can set defaults to 1 to
  1219.     fill in the default-keytable
  1220.  
  1221.     RETURN
  1222.     KEYTABLE *
  1223.  
  1224.     DESCRIPTION
  1225.  
  1226.     NOTES
  1227.     useful only, if we are using multiple keytables
  1228.  
  1229.     if we can fill in only parts of the deafult-information,
  1230.     we do NOT fail
  1231.  
  1232.     BUGS
  1233.  
  1234.     EXAMPLES
  1235.  
  1236.     SEE ALSO
  1237.  
  1238.     INTERNALS
  1239.  
  1240.     HISTORY
  1241.     27 Jan 1993 b_null created
  1242.  
  1243. ******************************************************************************/
  1244.  
  1245. KEYTABLE * new_keytable (char * name, int defaults)
  1246. {
  1247.     KEYTABLE * kt;
  1248.  
  1249.     if (kt = get_keytable(name)) {
  1250.     return (kt);
  1251.     } /* if */
  1252.  
  1253.     kt = AllocFunc (sizeof(KEYTABLE), MEMF_ANY);
  1254.     if (kt == NULL) {
  1255.     return (NULL);
  1256.     } /* if */
  1257.  
  1258.     setmem (kt, sizeof(KEYTABLE), 0);
  1259.     kt->node.ln_Name = DupFunc (name, MEMF_ANY);
  1260.     if (kt->node.ln_Name == NULL) {
  1261.     FreeFunc (kt, sizeof (KEYTABLE));
  1262.     return (NULL);
  1263.     } /* if */
  1264.  
  1265.     if (defaults) {
  1266.     resethash (kt);
  1267.     } /* if */
  1268.  
  1269.     AddTail ((struct List *)&KeyTables, &kt->node);
  1270.  
  1271.     return (kt);
  1272. } /* new_keytable */
  1273.  
  1274.  
  1275.  
  1276. /*****************************************************************************
  1277.  
  1278.     NAME
  1279.     init_keytables
  1280.     exit_keytables
  1281.  
  1282.     PARAMETER
  1283.     void
  1284.  
  1285.     RESULT
  1286.     -/-
  1287.  
  1288.     RETURN
  1289.     void
  1290.  
  1291.     DESCRIPTION
  1292.     init and exit functions for keytables
  1293.  
  1294.     NOTES
  1295.     useful only, if we are using multiple keytables
  1296.  
  1297.     THESE are __AUTOEXIT/__AUTOEXIT - functions !!!!
  1298.  
  1299.     HISTORY
  1300.     27 Jan 1993 b_null created
  1301.  
  1302. ******************************************************************************/
  1303.  
  1304.  
  1305. MK_AUTOINIT( init_keytables )
  1306. {
  1307.     NewList     ((struct List*)&KeyTables);
  1308.     new_keytable ("default",1);
  1309. } /* init_keytables */
  1310.  
  1311.  
  1312. MK_AUTOEXIT( exit_keytables )
  1313. {
  1314.     KEYTABLE * kt;
  1315.  
  1316. /* PutStr ("key_exiting\n"); */
  1317.     while (kt = GetHead (&KeyTables)) {
  1318.     delete_keytable (kt, 1);
  1319.     } /* while */
  1320. /* PutStr ("key_exited\n"); */
  1321. } /* exit_keytables */
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327. /******************************************************************************
  1328. *****  ENDE keytables.c
  1329. ******************************************************************************/
  1330.